package com.mxx.common.thread;

import com.mxx.common.exception.UnsupportedException;
import com.mxx.common.utils.Strings;
import io.netty.util.concurrent.FastThreadLocal;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author itzgyw
 * @Date 2020-01-22
 * @Time 17:12
 * @Description:
 */
public class FastThreadContext {
    private static FastThreadLocal<Map<String, Object>> threadContent;


    public static <T> Optional<T> get(String key) {
        return Optional.ofNullable((T) getContent().get(key));
    }

    public static <T> T getThrowNull(String key, String msg) {
        T t = (T) getContent().get(key);
        if (t == null) {
            if (Strings.isEmpty(msg)) {
                throw new IllegalArgumentException(" FastThreadContext.getThrowNull msg is empty");
            }
            throw new NullPointerException(msg);
        }
        return t;
    }

    public static <T> void set(String key, T t) {
        Map<String, Object> threadMap = getContent();
        Object val = threadMap.get(key);
        if (val != null) {
            throw new UnsupportedException(" unsupported manipulation type, a value already exists in the thread");
        }
        threadMap.put(key, t);
    }

    public static void remove(String... keyArray) {

        Map<String, Object> map = getContent();
        for (int index = 0; index < keyArray.length; index++) {
            map.remove(keyArray[index]);
        }
    }

    public static void removeAll() {
        getContent().clear();
    }


    public static Map<String, Object> getContent() {

        if (threadContent == null) {
            synchronized (FastThreadContext.class) {
                if (threadContent == null) {
                    threadContent = new FastThreadLocal();
                    threadContent.set(new ConcurrentHashMap<>());
                }
            }
        }
        Map<String, Object> threadMap = threadContent.get();
        if (threadMap == null) {
            synchronized (FastThreadContext.class) {
                if (threadMap == null) {
                    threadMap = new ConcurrentHashMap<>();
                    threadContent.set(threadMap);
                }
            }
        }
        return threadMap;
    }

    public static Set<String> keySet() {
        return new HashSet<>(getContent().keySet());
    }

}
